﻿using Authentication.Configuration;
using Authentication.Model.Model;
using Authentication.Model.ViewModel.Account;
using Authentication.Web.Service;
using Common.Contract;
using Common.Contract.Authentication;
using Common.Contract.Authentication.Record;
using Common.Contract.Authentication.Request;
using Common.Contract.Authentication.Response;
using Common.Contract.Paging;
using Common.Service;
using Common.Util;
using Common.Service.DataTables;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
using System.Web.Security;
using Common.Contract.SystemConfig;
using Common.Contract.SystemConfig.Record;
using Common.Contract.SystemConfig.Request;
using Common.Cache;
using Common.Type;
using System.Globalization;
using Newtonsoft.Json;

namespace Authentication.Web.Controller
{
    public class AccountController : ControllerBase
    {
        #region Login actions
        [AllowAnonymous]
        public ActionResult Login(string returnUrl)
        {
            if (!string.IsNullOrEmpty(this.CurrentUser))
                return Redirect("~/");
            //ViewBag.ReturnUrl = returnUrl;
            return View();
        }

        //
        // POST: /Account/Login
        [HttpPost]
        [AllowAnonymous]
        public ActionResult Login(LoginViewModel vm)
        {
            ModelState.Clear(); //clear old status
            try
            {
                if (HttpContext != null && HttpContext.Session != null) HttpContext.Session.Clear();
                if (ModelState.IsValid)
                {
                    vm.UserName = vm.UserName.ToUpper();
                    using (ServiceClient<IAuthentication> serviceClient = new ServiceClient<IAuthentication>())
                    {
                        UserRecord request = new UserRecord { ApplicationKey = SystemConfiguration.ApplicationKey, UserName = vm.UserName, Password = vm.Password };
                        var response = serviceClient.Proxy.CheckLogin(request);
                        if (response.IsSuccess)
                        {
                            // Save cookie when Login success
                            FormsAuthentication.SetAuthCookie(vm.UserName, vm.IsRemember);

                            //if (Url.IsLocalUrl(vm.ReturnUrl) && vm.ReturnUrl.Length > 1 && vm.ReturnUrl.StartsWith("/")
                            //    && !vm.ReturnUrl.StartsWith("//") && !vm.ReturnUrl.StartsWith("/\\"))
                            //{
                            //    return Redirect(vm.ReturnUrl);
                            //}
                            return RedirectToAction("Index", "Home", new { area = string.Empty });
                        }
                        else
                        {
                            vm.MessageType = MessageType.Error;
                            vm.Message = response.ErrorMessage;
                            return View(vm);
                        }
                    }
                }
                //string Current user = User.Identity.Name;
                // If we got this far, something failed, redisplay form 
                vm.MessageType = MessageType.Error;
                vm.Message = @"The user name or password provided is incorrect.";
                return View(vm);
            }
            catch (Exception ex)
            {
                vm.MessageType = MessageType.Error;
                vm.Message = ex.ToString();
                return View(vm);
            }
        }
        #endregion

        #region Register user actions
        [Authorize]
        public ActionResult Register()
        {
            RegisterUserViewModel vm = new RegisterUserViewModel();

            //Make verification number
            Random rand = new Random();
            int numnum = rand.Next(10000, 99999);
            string path = Server.MapPath("~/content/img");
            string pathFull = numnum.SaveVerifyCode(path);
            using (ServiceClient<IConfiguration> serviceClient = new ServiceClient<IConfiguration>())
            {
                RequestHeaderRecord header = new RequestHeaderRecord { ApplicationKey = SystemConfiguration.ApplicationKey, CallerName = "Authentication.Web.Controller.Register" };

                //Clear old data
                SearchDictionaryRequest request = new SearchDictionaryRequest
                {
                    Header = header,
                    IsOutTime = true,
                    MaxMinuteLife = 5
                };
                var response = serviceClient.Proxy.SearchDictionary(request);
                if (response.IsSuccess)
                {
                    //Clear dictionary  
                    DeleteDictionaryRequest request2 = new DeleteDictionaryRequest
                    {
                        Header = header,
                        Keys = response.Records.Select(x => x.Key).ToList()
                    };
                    var response2 = serviceClient.Proxy.DeleteDictionary(request2);

                    foreach (var item in response.Records)
                    {
                        string path2 = Server.MapPath("~/content/img/" + item.Key);
                        try { System.IO.File.Delete(path2); }
                        catch { }
                    }
                }


                //Create new data
                DictionaryRecord record = new DictionaryRecord { ApplicationKey = SystemConfiguration.ApplicationKey, Key = pathFull, Value = numnum.ToString() };
                AddDictionaryRequest request3 = new AddDictionaryRequest
                {
                    Header = header,
                    Record = record
                };

                var response3 = serviceClient.Proxy.AddDictionary(request3);
            }

            vm.VerificationImageUrl = pathFull;

            return View(vm);
        }

        [Authorize]
        [HttpPost]
        public ActionResult Register(RegisterUserViewModel vm)
        {
            using (ServiceClient<IConfiguration> serviceClient = new ServiceClient<IConfiguration>())
            {
                RequestHeaderRecord header = new RequestHeaderRecord { ApplicationKey = SystemConfiguration.ApplicationKey, CallerName = "Authentication.Web.Controller.Register" };
                SearchDictionaryRequest request = new SearchDictionaryRequest
                {
                    Header = header,
                    Key = vm.VerificationImageUrl,
                };

                //Check validate
                var response = serviceClient.Proxy.SearchDictionary(request);
                bool success = false;
                if (response.IsSuccess)
                {
                    //Do when validate 
                    if (response.Records[0].Key == vm.VerificationImageUrl && response.Records[0].Value == vm.VerificationCode)
                    {
                        RegisterUserRequest registerUserRequest = new RegisterUserRequest
                        {
                            Header = header,
                            Record = new UserRecord
                            {
                                ApplicationKey = SystemConfiguration.ApplicationKey,
                                Email = vm.Email,
                                FirstName = vm.FirstName,
                                LastName = vm.LastName,
                                Mobile = vm.Mobile,
                                ImageUrl = vm.ImageUrl,
                                Password = vm.Password.ToSHAPassword(),
                                UserName = vm.UserName,
                                GroupIdentifier = SystemConfiguration.RegisterGroup,
                                CreationDate = DateTime.Now
                            }
                        };
                        using (ServiceClient<IAuthentication> serviceClientUser = new ServiceClient<IAuthentication>())
                        {

                            var registerUserResponse = serviceClientUser.Proxy.RegisterUser(registerUserRequest);
                            if (response.IsSuccess)
                            {
                                return RedirectToAction("Index");
                            }
                        }
                    }
                }


                //delete file img 
                string path = Server.MapPath("~/content/img/" + vm.VerificationImageUrl);
                try { System.IO.File.Delete(path); }
                catch { }

                //delete from dictionary
                DeleteDictionaryRequest request2 = new DeleteDictionaryRequest
                {
                    Header = header,
                    Keys = new List<string> { vm.VerificationImageUrl }
                };
                serviceClient.Proxy.DeleteDictionary(request2);


                //Recreate new random Capchar
                Random rand = new Random();
                int numnum = rand.Next(10000, 99999);
                string path2 = Server.MapPath("~/content/img");
                string pathFull = numnum.SaveVerifyCode(path2);
                vm.VerificationImageUrl = pathFull;
                vm.VerificationCode = numnum.ToString();

                //Create new data
                DictionaryRecord record = new DictionaryRecord { ApplicationKey = SystemConfiguration.ApplicationKey, Key = pathFull, Value = numnum.ToString() };
                AddDictionaryRequest request3 = new AddDictionaryRequest
                {
                    Header = header,
                    Record = record
                };
                var response3 = serviceClient.Proxy.AddDictionary(request3);
            }


            return View(vm);
        }
        #endregion

        #region Profile
        [Authorize]
        [HttpGet]
        public ActionResult Profile(string account)
        {
            ProfileViewModel vm = new ProfileViewModel();
            UserRecord userRecord = null;
            if (string.IsNullOrWhiteSpace(account))
            {
                userRecord = CurrentUserRecord;
            }
            else
            {
                using (ServiceClient<IAuthentication> serviceClient = new ServiceClient<IAuthentication>())
                {
                    RetrieveUserByUserNameRequest request = new RetrieveUserByUserNameRequest
                    {
                        Header = new RequestHeaderRecord
                        {
                            ApplicationKey = this.ApplicationKey,
                            CallerName = "Authentication.Web.Controller.AccountController.Profile"
                        },
                        UserName = CurrentUser
                    };
                    var objectResponse = serviceClient.Proxy.RetrieveUserByUserName(request);
                    userRecord = objectResponse.Record;
                }
            }

            var objects = CacheFactory.MemCache.GetFromCache<IEnumerable<ObjectRecord>>(CACHING_NAME.LIST_ALL_OBJECTS, () =>
            {
                //Get object with the rules
                IEnumerable<ObjectRecord> objectsSub = null;
                using (ServiceClient<IAuthentication> serviceClient = new ServiceClient<IAuthentication>())
                {
                    RetrieveObjectsRequest request = new RetrieveObjectsRequest
                    {
                        Header = new RequestHeaderRecord
                        {
                            ApplicationKey = SystemConfiguration.ApplicationKey,
                            CallerName = "Authentication.Web.Controller.AccountController.GetMenuNodes"
                        }
                    };
                    var objectResponse = serviceClient.Proxy.RetrieveObjects(request);
                    objectsSub = objectResponse.Records;
                }
                return objectsSub;
            });
            vm.Objects = objects == null ? new List<ObjectRecord>() : objects.ToList();
            if (userRecord != null)
            {
                vm.FirstName = userRecord.FirstName;
                vm.LastName = userRecord.LastName;
                vm.Mobile = userRecord.Mobile;
                vm.UserName = userRecord.UserName;
                vm.ImageUrl = userRecord.ImageUrl;
                vm.FullName = string.Format("{0} {1}", vm.FirstName, vm.LastName);
                if (vm.FullName.IsNullOrWhiteSpace()) vm.FullName = vm.UserName;
                vm.Active = userRecord.Active;
                vm.CreationDate = userRecord.CreationDate;
                vm.GroupName = userRecord.GroupName;
                if (userRecord.Birthday.HasValue) vm.Birthday = userRecord.Birthday.Value.ToString("MM/dd/yyyy");
                vm.Email = userRecord.Email;
                vm.Address = userRecord.Address;
                vm.Gender = userRecord.Gender;
            }
            return View(vm);
        }

        [Authorize]
        [HttpPost]
        public ActionResult Profile(ProfileViewModel vm, FormCollection form)
        {
            try
            {
                if (form["btnUpdate"] != null)
                {
                    if (vm.UserName.IsNullOrWhiteSpace()) vm.UserName = CurrentUser;
                    return UpdateProfile(vm);
                }
            }
            catch (Exception ex)
            {
                vm.MessageType = MessageType.Error;
                vm.Message = ex.ToString();
            }

            return View(vm); ;
        }

        //Do Updating profile
        private ActionResult UpdateProfile(ProfileViewModel vm)
        {
            UserRecord userRecord = new UserRecord
            {
                UserName = vm.UserName,
                Address = vm.Address,
                ApplicationKey = this.ApplicationKey,
                Email = vm.Email,
                FirstName = vm.FirstName,
                Gender = vm.Gender,
                //ImageUrl = ,
                Birthday = vm.Birthday.ToDateTime(SystemConfiguration.DateTimeFormat),
                LastName = vm.LastName,
                Mobile = vm.Mobile,
                Active = vm.UserName.Equals(CurrentUser, StringComparison.OrdinalIgnoreCase) ? true : vm.Active
            };

            if (vm.UserName.IsNullOrWhiteSpace()) vm.UserName = CurrentUser;

            var objects = CacheFactory.MemCache.GetFromCache<IEnumerable<ObjectRecord>>(CACHING_NAME.LIST_ALL_OBJECTS, () =>
            {
                //Get object with the rules
                IEnumerable<ObjectRecord> objectsSub = null;
                using (ServiceClient<IAuthentication> serviceClient = new ServiceClient<IAuthentication>())
                {
                    RetrieveObjectsRequest request = new RetrieveObjectsRequest
                    {
                        Header = new RequestHeaderRecord
                        {
                            ApplicationKey = SystemConfiguration.ApplicationKey,
                            CallerName = "Authentication.Web.Controller.AccountController.UpdateProfile"
                        }
                    };
                    var objectResponse = serviceClient.Proxy.RetrieveObjects(request);
                    objectsSub = objectResponse.Records;
                }
                return objectsSub;
            });
            vm.Objects = objects == null ? new List<ObjectRecord>() : objects.ToList();

            using (ServiceClient<IAuthentication> serviceClient = new ServiceClient<IAuthentication>())
            {
                UpdateUserRequest request = new UpdateUserRequest
                {
                    Header = new RequestHeaderRecord
                    {
                        ApplicationKey = this.ApplicationKey,
                        CallerName = "Authentication.Web.Controller.AccountController.UpdateProfile"
                    },
                    Record = userRecord
                };
                var objectResponse = serviceClient.Proxy.UpdateUser(request);
                if (objectResponse.IsSuccess)
                {
                    return RedirectToAction("profile", "account", string.Compare(userRecord.UserName, CurrentUser, true) == 0 ? null : userRecord.UserName);
                }
                else
                {
                    vm.MessageType = MessageType.Error;
                    vm.Message = string.Format("Can not update profile, ErrorMessage={0}", objectResponse.ErrorMessage);
                    return View(vm);
                }
            }
        }
        #endregion

        #region LogOut
        [HttpGet]
        public ActionResult LogOut(string code)
        {
            if (string.Compare(code, CurrentUser, true) == 0)
            {
                if (HttpContext != null && HttpContext.Session != null) HttpContext.Session.Clear();
                FormsAuthentication.SignOut();
                return RedirectToAction("login");
            }
            else
            {
                return RedirectToAction("index", "home");
            }
        }
        #endregion

        #region Groups
        [Authorize]
        public ActionResult Groups()
        {
            GroupViewModel vm = new GroupViewModel { IsSupperAdmin = CurrentUser.Equals(SystemConfiguration.SUPPER_ADMIN, StringComparison.OrdinalIgnoreCase) };
            return View(vm);
        }

        [HttpPost]
        [Authorize]
        public ActionResult Groups(GroupViewModel vm, string btnClick)
        {
            var record = new GroupRecord
            {
                ApplicationKey = SystemConfiguration.ApplicationKey,
                GroupIdentifier = vm.GroupIdentifier,
                GroupName = vm.GroupName,
                Description = vm.Description,
                CreationDate = vm.CreationDate.ToDateTime(SystemConfiguration.DateTimeFormat),
                UpdateDate = vm.UpdateDate.ToDateTime(SystemConfiguration.DateTimeFormat)
            };

            var header = new RequestHeaderRecord
            {
                ApplicationKey = SystemConfiguration.ApplicationKey,
                CallerName = "Authentication.Web.Controller.AccountController.Groups"
            };

            using (ServiceClient<IAuthentication> serviceClient = new ServiceClient<IAuthentication>())
            {
                ResponseRecord response = null;
                if (btnClick.Equals("btnNewGroup", System.StringComparison.OrdinalIgnoreCase))
                {
                    AddGroupRequest request = new AddGroupRequest
                    {
                        Header = header,
                        Record = record
                    };
                    response = serviceClient.Proxy.AddGroup(request);
                }
                else
                {

                    UpdateGroupRequest request = new UpdateGroupRequest
                    {
                        Header = header,
                        Record = record
                    };
                    response = serviceClient.Proxy.UpdateGroup(request);
                }


                if (response != null || response.IsSuccess)
                {
                    CacheFactory.MemCache.RemoveFromCache(string.Format(CACHING_NAME.CURRENT_USER_GROUP, this.CurrentUser), true);
                    return RedirectToAction("groups", "account");
                }
                else
                {
                    vm.Message = response.ErrorMessage;
                    vm.MessageType = MessageType.Error;
                }
            }
            return View(vm);
        }


        [Authorize]
        [HttpPost]
        public ActionResult Delete_Group(string code)
        {
            using (ServiceClient<IAuthentication> serviceClient = new ServiceClient<IAuthentication>())
            {
                DeleteGroupRequest request = new DeleteGroupRequest
                {
                    Header = new RequestHeaderRecord
                    {
                        ApplicationKey = SystemConfiguration.ApplicationKey,
                        CallerName = "Authentication.Web.Controller.AccountController.Groups"
                    },
                    Record = code
                };
                var response = serviceClient.Proxy.DeleteGroup(request);
                if (response.IsSuccess)
                {
                    CacheFactory.MemCache.RemoveFromCache(string.Format(CACHING_NAME.CURRENT_USER_GROUP, this.CurrentUser), true);
                }

                return Json(response);
            }
        }

        [HttpPost]
        [Authorize]
        public ActionResult GroupsData(DataTablesPageRequest pageRequest)
        {
            DataTableResponse pageResponse = null;
            using (ServiceClient<IAuthentication> serviceClient = new ServiceClient<IAuthentication>())
            {
                RetrieveGroupsRequest request = new RetrieveGroupsRequest
                {
                    Header = new RequestHeaderRecord
                    {
                        ApplicationKey = SystemConfiguration.ApplicationKey,
                        CallerName = "Authentication.Web.Controller.AccountController.GroupsData"
                    },
                    Name = pageRequest.Search.Trim(),
                    Page = new PageRecord
                    {
                        PageSize = pageRequest.DisplayLength,
                        PageIndex = pageRequest.DisplayLength > 0 ? pageRequest.DisplayStart / pageRequest.DisplayLength : 0
                    }
                };

                var applicationRecord = serviceClient.Proxy.RetrieveGroups(request);
                var response = (applicationRecord == null || applicationRecord.Records == null) ? new List<GroupRecord>() : applicationRecord.Records;
                pageResponse = new DataTableResponse
                {
                    sEcho = pageRequest.Echo,
                    iTotalRecords = applicationRecord.Page.TotalRecords,
                    sColumns = pageRequest.ColumnNames,
                    aaData = response.Select(x => new object[]{
                                                                x.GroupIdentifier, 
                                                                x.GroupName,
                                                                x.Description??string.Empty,
                                                                x.CreationDate
                                                               }).ToList()
                };
            }
            return Json(pageResponse);
        }
        #endregion

        #region Users
        [Authorize]
        public ActionResult Users()
        {
            ModelState.Clear();
            var header = new RequestHeaderRecord
            {
                ApplicationKey = SystemConfiguration.ApplicationKey,
                CallerName = "Authentication.Web.Controller.AccountController.Users"
            };

            UserViewModel vm = new UserViewModel { IsSupperAdmin = CurrentUser.Equals(Authentication.Configuration.SystemConfiguration.SUPPER_ADMIN, StringComparison.OrdinalIgnoreCase) };
            using (ServiceClient<IAuthentication> serviceClient = new ServiceClient<IAuthentication>())
            {
                RetrieveGroupsRequest request = new RetrieveGroupsRequest { Header = header };
                var response = serviceClient.Proxy.RetrieveGroups(request);
                if (response.IsSuccess)
                {
                    vm.Groups = response.Records;
                }
            }
            return View(vm);
        }

        [HttpPost]
        [Authorize]
        public ActionResult Users(UserViewModel vm, string btnClick)
        {
            var header = new RequestHeaderRecord
            {
                ApplicationKey = SystemConfiguration.ApplicationKey,
                CallerName = "Authentication.Web.Controller.AccountController.Users-HttpPost"
            };

            using (ServiceClient<IAuthentication> serviceClient = new ServiceClient<IAuthentication>())
            {
                //Group of user
                RetrieveGroupsRequest requestGroup = new RetrieveGroupsRequest { Header = header };
                var responserequestGroup = serviceClient.Proxy.RetrieveGroups(requestGroup);
                if (responserequestGroup.IsSuccess)
                {
                    vm.Groups = responserequestGroup.Records;
                }

                RetrieveUserByUserNameRequest requestRetrieve = new RetrieveUserByUserNameRequest
                {
                    Header = header,
                    UserName = vm.UserName,
                };
                var responseRetrieve = serviceClient.Proxy.RetrieveUserByUserName(requestRetrieve);

                if (btnClick.Equals("btnNewUser", System.StringComparison.OrdinalIgnoreCase))
                {
                    if (responseRetrieve.IsSuccess)
                    {
                        vm.Message = string.Format("There is an existing user with username = {0}, email={1}", vm.UserName, vm.Email);
                        vm.MessageType = MessageType.Error;
                        return View(vm);
                    }
                    else
                    {
                        UserRecord record = new UserRecord
                         {
                             ApplicationKey = SystemConfiguration.ApplicationKey,
                             Email = vm.Email,
                             FirstName = vm.FirstName,
                             LastName = vm.LastName,
                             Mobile = vm.Mobile,
                             ImageUrl = vm.ImageUrl,
                             Password = StringExtensions.CreateRandomPassword(8).ToSHAPassword(),
                             UserName = vm.UserName,
                             GroupIdentifier = vm.GroupIdentifier,
                             CreationDate = DateTime.Now
                         };

                        RegisterUserRequest registerUserRequest = new RegisterUserRequest
                        {
                            Header = header,
                            Record = record
                        };

                        var responseAdd = serviceClient.Proxy.RegisterUser(registerUserRequest);
                        if (responseAdd != null && responseAdd.IsSuccess)
                        {
                            return RedirectToAction("users", "account");
                        }
                        else
                        {
                            vm.Message = responseAdd.ErrorMessage;
                            vm.MessageType = MessageType.Error;
                        }
                    }
                }
                else
                {
                    if (responseRetrieve.IsSuccess)
                    {
                        var record = responseRetrieve.Record;
                        record.UserName = vm.UserName;
                        record.Email = vm.Email;
                        record.FirstName = vm.FirstName;
                        record.LastName = vm.LastName;
                        record.Mobile = vm.Mobile;
                        record.GroupIdentifier = vm.GroupIdentifier;
                        UpdateUserRequest request = new UpdateUserRequest
                        {
                            Header = header,
                            Record = record
                        };
                        var response = serviceClient.Proxy.UpdateUser(request);

                        if (response != null && response.IsSuccess)
                        {
                            return RedirectToAction("users", "account");
                        }
                        else
                        {
                            vm.Message = response.ErrorMessage;
                            vm.MessageType = MessageType.Error;
                        }
                    }
                    else
                    {
                        vm.Message = responseRetrieve.ErrorMessage;
                        vm.MessageType = MessageType.Error;
                    }
                }
            }
            return View(vm);
        }

        [Authorize]
        [HttpPost]
        public ActionResult Active_User(string code, bool active)
        {
            var header = new RequestHeaderRecord
            {
                ApplicationKey = SystemConfiguration.ApplicationKey,
                CallerName = "Authentication.Web.Controller.AccountController.Active_User"
            };

            if (string.Compare(code, SystemConfiguration.SUPPER_ADMIN, StringComparison.OrdinalIgnoreCase) == 0)
            {
                ResponseRecord response = new ResponseRecord { IsSuccess = false, ErrorMessage = "Can not active/deactive super admin." };
                return Json(response);
            }

            using (ServiceClient<IAuthentication> serviceClient = new ServiceClient<IAuthentication>())
            {
                RetrieveUserByUserNameRequest requestRetrieve = new RetrieveUserByUserNameRequest
                {
                    Header = header,
                    UserName = code,
                };
                var responseRetrieve = serviceClient.Proxy.RetrieveUserByUserName(requestRetrieve);
                if (responseRetrieve.IsSuccess)
                {
                    responseRetrieve.Record.Active = !active;
                    UpdateUserRequest request = new UpdateUserRequest
                    {
                        Header = header,
                        Record = responseRetrieve.Record
                    };
                    var response = serviceClient.Proxy.UpdateUser(request);
                    return Json((ResponseRecord)response);
                }
                return Json((ResponseRecord)responseRetrieve);
            }
        }

        [HttpPost]
        [Authorize]
        public ActionResult UsersData(DataTablesPageRequest pageRequest)
        {
            DataTableResponse pageResponse = null;
            using (ServiceClient<IAuthentication> serviceClient = new ServiceClient<IAuthentication>())
            {
                RetrieveUsersRequest request = new RetrieveUsersRequest
                {
                    Header = new RequestHeaderRecord
                    {
                        ApplicationKey = SystemConfiguration.ApplicationKey,
                        CallerName = "Authentication.Web.Controller.AccountController.UsersData"
                    },
                    Name = pageRequest.Search.Trim(),
                    Page = new PageRecord
                    {
                        PageSize = pageRequest.DisplayLength,
                        PageIndex = pageRequest.DisplayLength > 0 ? pageRequest.DisplayStart / pageRequest.DisplayLength : 0
                    }
                };

                var applicationRecord = serviceClient.Proxy.RetrieveUsers(request);
                var response = (applicationRecord == null || applicationRecord.Records == null) ? new List<UserRecord>() : applicationRecord.Records;
                pageResponse = new DataTableResponse
                {
                    sEcho = pageRequest.Echo,
                    iTotalRecords = applicationRecord.Page.TotalRecords,
                    sColumns = pageRequest.ColumnNames,
                    aaData = response.Select(x => new object[]{
                                                                x.UserName, 
                                                                x.Email,
                                                                x.FirstName??string.Empty,
                                                                x.LastName??string.Empty,
                                                                x.Mobile??string.Empty,
                                                                x.Active,
                                                                x.GroupIdentifier??string.Empty
                                                               }).ToList()
                };
            }
            return Json(pageResponse);
        }
        #endregion

        #region Assign users to group
        [Authorize]
        public ActionResult Assign_Group()
        {
            var header = new RequestHeaderRecord
            {
                ApplicationKey = SystemConfiguration.ApplicationKey,
                CallerName = "Authentication.Web.Controller.AccountController.Assign_Group"
            };


            OTP.Instant.Counter = ulong.Parse(DateTime.UtcNow.ToString(SystemConfiguration.CounterDateTimeFormat));
            AssignGroupViewModel vm = new AssignGroupViewModel { IsSupperAdmin = CurrentUser.Equals(Authentication.Configuration.SystemConfiguration.SUPPER_ADMIN, StringComparison.OrdinalIgnoreCase), OtpCounter = OTP.Instant.Counter, Otp = OTP.Instant.GetCurrentOTP() };
            using (ServiceClient<IAuthentication> serviceClient = new ServiceClient<IAuthentication>())
            {
                RetrieveGroupsRequest request = new RetrieveGroupsRequest { Header = header };
                var response = serviceClient.Proxy.RetrieveGroups(request);
                if (response.IsSuccess)
                {
                    vm.Groups = response.Records;
                }

                RetrieveUsersRequest requestUsers = new RetrieveUsersRequest { Header = header };
                var responseUsers = serviceClient.Proxy.RetrieveUsers(requestUsers);
                if (responseUsers.IsSuccess)
                {
                    vm.Users = responseUsers.Records;
                }
            }
            return View(vm);
        }

        [Authorize]
        [HttpPost]
        public ActionResult Assign_Group(AssignGroupViewModel vm)
        {
            var header = new RequestHeaderRecord
            {
                ApplicationKey = SystemConfiguration.ApplicationKey,
                CallerName = "Authentication.Web.Controller.AccountController.Assign_Group"
            };

            if (vm.UsersName != null && vm.UsersName.Count > 0)
            {
                var ids = JsonConvert.DeserializeObject<List<string>>(vm.UsersName[0]);
                vm.UsersName = ids;
            }

            using (ServiceClient<IAuthentication> serviceClient = new ServiceClient<IAuthentication>())
            {
                if (!vm.UserName.IsNullOrWhiteSpace())
                {
                    return AssignAnUserToGroup(serviceClient, header, vm.GroupIdentifier, vm.UserName, vm.Checked);
                }

                if (vm.UsersName != null && vm.UsersName.Count > 0)
                {
                    return AssignUsersToGroup(serviceClient, header, vm.GroupIdentifier, vm.UsersName);
                }

            }

            ResponseRecord result = new ResponseRecord { IsSuccess = false, ErrorMessage = "There is an error while processing action assing group" };
            return Json(result);
        }


        [Authorize]
        [HttpPost]
        public ActionResult Users_In_Group(string groupidentifier, string otp, ulong counter)
        {
            OTP.Instant.Counter = counter;
            DateTime timeGet; bool validateOtp = false;
            if (DateTime.TryParseExact(counter.ToString(), SystemConfiguration.CounterDateTimeFormat, null, DateTimeStyles.None, out timeGet))
            {
                TimeSpan timeCheck = DateTime.UtcNow - timeGet;
                if (timeCheck.TotalSeconds <= SystemConfiguration.OTPLiveTime) validateOtp = true;
            }

            if (!validateOtp || OTP.Instant.GetCurrentOTP() != otp)
            {
                ResponseRecord res = new ResponseRecord
                {
                    IsSuccess = false,
                    ErrorMessage = "Invalidate OTP check request"
                };
                return Json(res);
            }

            if (groupidentifier.IsNullOrWhiteSpace())
            {
                ResponseRecord res2 = new ResponseRecord
                {
                    IsSuccess = false,
                    ErrorMessage = "Invalidate groupidentifier request - request null"
                };
                return Json(res2);
            }

            var header = new RequestHeaderRecord
            {
                ApplicationKey = SystemConfiguration.ApplicationKey,
                CallerName = "Authentication.Web.Controller.AccountController.Users_In_Group"
            };

            using (ServiceClient<IAuthentication> serviceClient = new ServiceClient<IAuthentication>())
            {

                RetrieveUsersRequest retrieveRequest = new RetrieveUsersRequest { Header = header, GroupIdentifier = groupidentifier };
                var response = serviceClient.Proxy.RetrieveUsers(retrieveRequest);
                if (response.IsSuccess)
                {
                    var records = response.Records;
                }
                else
                {
                    response.ErrorMessage = string.Format("Can not found any user with groupidentifier='{0}'", groupidentifier);
                }
                return Json(response);
            }
        }
        #endregion

        #region Assign objects to group
        [Authorize]
        public ActionResult Assign_Group_Objects()
        {
            var header = new RequestHeaderRecord
            {
                ApplicationKey = SystemConfiguration.ApplicationKey,
                CallerName = "Authentication.Web.Controller.AccountController.Assign_Group_Objects"
            };

            OTP.Instant.Counter = ulong.Parse(DateTime.UtcNow.ToString(SystemConfiguration.CounterDateTimeFormat));
            AssignGroupObjectViewModel vm = new AssignGroupObjectViewModel { IsSupperAdmin = CurrentUser.Equals(Authentication.Configuration.SystemConfiguration.SUPPER_ADMIN, StringComparison.OrdinalIgnoreCase), OtpCounter = OTP.Instant.Counter, Otp = OTP.Instant.GetCurrentOTP() };

            using (ServiceClient<IAuthentication> serviceClient = new ServiceClient<IAuthentication>())
            {
                RetrieveGroupsRequest request = new RetrieveGroupsRequest { Header = header };
                var response = serviceClient.Proxy.RetrieveGroups(request);
                if (response.IsSuccess)
                {
                    vm.Groups = response.Records;
                }

                RetrieveObjectsRequest requestObjects = new RetrieveObjectsRequest { Header = header };
                var responseObjects = serviceClient.Proxy.RetrieveObjects(requestObjects);
                if (responseObjects.IsSuccess)
                {
                    vm.Objects = responseObjects.Records;
                }

                SearchRolesRequest requestRole = new SearchRolesRequest { Header = header };
                var roleResponse = serviceClient.Proxy.SearchRoles(requestRole);
                if (roleResponse.IsSuccess)
                {
                    vm.Roles = roleResponse.Records;
                }

                UpdateGroupRoleViewModel(serviceClient, header, vm);
            }
            return View(vm);
        }

        [Authorize]
        [HttpPost]
        public ActionResult Assign_Group_Objects(AssignGroupObjectViewModel vm, string[] group_roles)
        {
            var header = new RequestHeaderRecord
            {
                ApplicationKey = SystemConfiguration.ApplicationKey,
                CallerName = "Authentication.Web.Controller.AccountController.Assign_Group_Objects"
            };

            CacheFactory.MemCache.RemoveFromCache(CACHING_NAME.CURRENT_USER_GROUP, true);
            CacheFactory.MemCache.RemoveFromCache(CACHING_NAME.CURRENT_USER_RECORD_RULES_DICT, true);

            using (ServiceClient<IAuthentication> serviceClient = new ServiceClient<IAuthentication>())
            {
                RetrieveGroupsRequest request = new RetrieveGroupsRequest { Header = header };
                var response = serviceClient.Proxy.RetrieveGroups(request);
                if (response.IsSuccess)
                {
                    vm.Groups = response.Records;
                }

                RetrieveObjectsRequest requestObjects = new RetrieveObjectsRequest { Header = header };
                var responseObjects = serviceClient.Proxy.RetrieveObjects(requestObjects);
                if (responseObjects.IsSuccess)
                {
                    vm.Objects = responseObjects.Records;
                }

                SearchRolesRequest requestRole = new SearchRolesRequest { Header = header };
                var roleResponse = serviceClient.Proxy.SearchRoles(requestRole);
                if (roleResponse.IsSuccess)
                {
                    vm.Roles = roleResponse.Records;
                }

                if (group_roles == null || group_roles.Length == 0)
                {
                    UpdateGroupRoleViewModel(serviceClient, header, vm);
                    vm.Message = "You have to select roles before";
                    vm.MessageType = MessageType.Error;
                    vm.Message = vm.Message;
                    return View(vm);
                }

                var objectRoles = group_roles.Select(x => JsonConvert.DeserializeObject<AssignRole>("{" + x + "}")).ToList();
                RetrieveGroupRolesRequest retrieveRoleRequest = new RetrieveGroupRolesRequest
                {
                    Header = header,
                    GroupIdentifier = vm.GroupIdentifier
                };

                var retrieveRoleRequestResponse = serviceClient.Proxy.RetrieveGroupRoles(retrieveRoleRequest);
                if (retrieveRoleRequestResponse.IsSuccess)
                {
                    var deletedGroupRoleRecord = retrieveRoleRequestResponse.Records.Where(x => !objectRoles.Any(y => y.RoleIdentifier == x.RoleIdentifier && y.ObjectIdentifier == x.ObjectIdentifier)).ToList();
                    if (deletedGroupRoleRecord != null && deletedGroupRoleRecord.Count > 0)
                    {
                        var deletedGroupRoleRequest = new DeleteGroupRolesRequest { Record = deletedGroupRoleRecord, Header = header };
                        var deletedGroupRoleResponse = serviceClient.Proxy.DeleteGroupRoles(deletedGroupRoleRequest);
                        if (!deletedGroupRoleResponse.IsSuccess)
                        {
                            UpdateGroupRoleViewModel(serviceClient, header, vm);
                            vm.Message = deletedGroupRoleResponse.ErrorMessage;
                            vm.MessageType = MessageType.Error;
                            vm.Message = vm.Message;
                            return View(vm);
                        }
                    }

                    var savedGroupRoleRecords = objectRoles.Select(item => new GroupRoleRecord
                    {
                        ApplicationKey = SystemConfiguration.ApplicationKey,
                        GroupIdentifier = vm.GroupIdentifier,
                        ObjectIdentifier = item.ObjectIdentifier,
                        RoleIdentifier = item.RoleIdentifier,
                        Active = true
                    }).ToList();
                    var savedGroupRoleRequest = new SaveGroupRolesRequest { Record = savedGroupRoleRecords, Header = header };
                    var savedGroupRoleResponse = serviceClient.Proxy.SaveGroupRoles(savedGroupRoleRequest);
                    if (!savedGroupRoleResponse.IsSuccess)
                    {
                        UpdateGroupRoleViewModel(serviceClient, header, vm);
                        vm.Message = savedGroupRoleResponse.ErrorMessage;
                        vm.MessageType = MessageType.Error;
                        vm.Message = vm.Message;
                        return View(vm);
                    }
                }
                return Redirect("/account/assign-group-objects");
            }
        }

        [Authorize]
        [HttpPost]
        public ActionResult Objects_In_Group(string groupidentifier, string otp, ulong counter)
        {
            OTP.Instant.Counter = counter;
            DateTime timeGet; bool validateOtp = false;
            if (DateTime.TryParseExact(counter.ToString(), SystemConfiguration.CounterDateTimeFormat, null, DateTimeStyles.None, out timeGet))
            {
                TimeSpan timeCheck = DateTime.UtcNow - timeGet;
                if (timeCheck.TotalSeconds <= SystemConfiguration.OTPLiveTime) validateOtp = true;
            }

            if (!validateOtp || OTP.Instant.GetCurrentOTP() != otp)
            {
                ResponseRecord res = new ResponseRecord
                {
                    IsSuccess = false,
                    ErrorMessage = "Invalidate OTP check request"
                };
                return Json(res);
            }

            if (groupidentifier.IsNullOrWhiteSpace())
            {
                ResponseRecord res2 = new ResponseRecord
                {
                    IsSuccess = false,
                    ErrorMessage = "Invalidate groupidentifier request - request null"
                };
                return Json(res2);
            }

            var header = new RequestHeaderRecord
            {
                ApplicationKey = SystemConfiguration.ApplicationKey,
                CallerName = "Authentication.Web.Controller.AccountController.Users_In_Group"
            };

            using (ServiceClient<IAuthentication> serviceClient = new ServiceClient<IAuthentication>())
            {

                RetrieveUsersRequest retrieveRequest = new RetrieveUsersRequest { Header = header, GroupIdentifier = groupidentifier };
                var response = serviceClient.Proxy.RetrieveUsers(retrieveRequest);
                if (response.IsSuccess)
                {
                    var records = response.Records;
                }
                else
                {
                    response.ErrorMessage = string.Format("Can not found any user with groupidentifier='{0}'", groupidentifier);
                }
                return Json(response);
            }
        }
        #endregion

        #region Assign objects to group
        [Authorize]
        public ActionResult Assign_User_Objects()
        {
            var header = new RequestHeaderRecord
            {
                ApplicationKey = SystemConfiguration.ApplicationKey,
                CallerName = "Authentication.Web.Controller.AccountController.Assign_User_Objects"
            };

            OTP.Instant.Counter = ulong.Parse(DateTime.UtcNow.ToString(SystemConfiguration.CounterDateTimeFormat));
            AssignUserObjectViewModel vm = new AssignUserObjectViewModel { IsSupperAdmin = CurrentUser.Equals(Authentication.Configuration.SystemConfiguration.SUPPER_ADMIN, StringComparison.OrdinalIgnoreCase), OtpCounter = OTP.Instant.Counter, Otp = OTP.Instant.GetCurrentOTP() };

            using (ServiceClient<IAuthentication> serviceClient = new ServiceClient<IAuthentication>())
            {
                RetrieveUsersRequest request = new RetrieveUsersRequest { Header = header };
                var response = serviceClient.Proxy.RetrieveUsers(request);
                if (response.IsSuccess)
                {
                    vm.Users = response.Records;
                }
                var dictUsers = vm.Users.ToDictionary(x => x.UserName);

                RetrieveObjectsRequest requestObjects = new RetrieveObjectsRequest { Header = header };
                var responseObjects = serviceClient.Proxy.RetrieveObjects(requestObjects);
                if (responseObjects.IsSuccess)
                {
                    vm.Objects = responseObjects.Records;
                }

                SearchRolesRequest requestRole = new SearchRolesRequest { Header = header };
                var roleResponse = serviceClient.Proxy.SearchRoles(requestRole);
                if (roleResponse.IsSuccess)
                {
                    vm.Roles = roleResponse.Records;
                }

                UpdateUserRoleViewModel(serviceClient, header, vm, dictUsers);
            }
            return View(vm);
        }

        [Authorize]
        [HttpPost]
        public ActionResult Assign_User_Objects(AssignUserObjectViewModel vm, string[] user_roles)
        {
            var header = new RequestHeaderRecord
            {
                ApplicationKey = SystemConfiguration.ApplicationKey,
                CallerName = "Authentication.Web.Controller.AccountController.Assign_User_Objects"
            };

            CacheFactory.MemCache.RemoveFromCache(CACHING_NAME.CURRENT_USER_OBJECT, true);
            CacheFactory.MemCache.RemoveFromCache(CACHING_NAME.CURRENT_USER_RECORD_RULES_DICT, true);

            using (ServiceClient<IAuthentication> serviceClient = new ServiceClient<IAuthentication>())
            {
                RetrieveUsersRequest request = new RetrieveUsersRequest { Header = header };
                var response = serviceClient.Proxy.RetrieveUsers(request);
                if (response.IsSuccess)
                {
                    vm.Users = response.Records;
                }

                RetrieveObjectsRequest requestObjects = new RetrieveObjectsRequest { Header = header };
                var responseObjects = serviceClient.Proxy.RetrieveObjects(requestObjects);
                if (responseObjects.IsSuccess)
                {
                    vm.Objects = responseObjects.Records;
                }

                SearchRolesRequest requestRole = new SearchRolesRequest { Header = header };
                var roleResponse = serviceClient.Proxy.SearchRoles(requestRole);
                if (roleResponse.IsSuccess)
                {
                    vm.Roles = roleResponse.Records;
                }

                var dictUsers = vm.Users.ToDictionary(x => x.UserName);
                var selectedGroupIdentifier = dictUsers.ContainsKey(vm.UserName) ? dictUsers[vm.UserName].GroupIdentifier : string.Empty;
                if (user_roles == null || user_roles.Length == 0)
                {
                    UpdateUserRoleViewModel(serviceClient, header, vm, dictUsers);
                    vm.Message = "You have to select roles before";
                    vm.MessageType = MessageType.Error;
                    vm.Message = vm.Message;
                    return View(vm);
                }

                var objectRoles = user_roles.Select(x => JsonConvert.DeserializeObject<AssignRole>("{" + x + "}")).ToList();
                RetrieveUserRolesRequest retrieveRoleRequest = new RetrieveUserRolesRequest
                {
                    Header = header,
                    UserName = vm.UserName
                };

                List<GroupRoleRecord> groupRoles = new List<GroupRoleRecord>();
                if (dictUsers.ContainsKey(vm.UserName))
                {
                    RetrieveGroupRolesRequest retrieveGroupRoleRequest = new RetrieveGroupRolesRequest
                    {
                        Header = header,
                        GroupIdentifier = dictUsers[vm.UserName].GroupIdentifier
                    };

                    var retrieveGroupRoleResponse = serviceClient.Proxy.RetrieveGroupRoles(retrieveGroupRoleRequest);
                    if (retrieveGroupRoleResponse.IsSuccess)
                    {
                        groupRoles = retrieveGroupRoleResponse.Records;
                    }
                }


                var retrieveRoleResponse = serviceClient.Proxy.RetrieveUserRoles(retrieveRoleRequest);
                if (retrieveRoleResponse.IsSuccess)
                {
                    //Update conflig User role & Group role
                    var updatedUserRoleRecords = groupRoles.Where(x => !objectRoles.Any(y => y.RoleIdentifier == x.RoleIdentifier && y.ObjectIdentifier == x.ObjectIdentifier))
                    .Select(item => new UserRoleRecord
                    {
                        ApplicationKey = SystemConfiguration.ApplicationKey,
                        UserName = vm.UserName,
                        ObjectIdentifier = item.ObjectIdentifier,
                        RoleIdentifier = item.RoleIdentifier,
                        Active = false
                    }).ToList();
                    if (updatedUserRoleRecords != null && updatedUserRoleRecords.Count > 0)
                    {
                        var updateUserRoleRequest = new SaveUserRolesRequest { Record = updatedUserRoleRecords, Header = header };
                        var updateUserRoleResponse = serviceClient.Proxy.SaveUserRoles(updateUserRoleRequest);
                        if (!updateUserRoleResponse.IsSuccess)
                        {
                            UpdateUserRoleViewModel(serviceClient, header, vm, dictUsers);
                            vm.Message = updateUserRoleResponse.ErrorMessage;
                            vm.MessageType = MessageType.Error;
                            vm.Message = vm.Message;
                            return View(vm);
                        }
                    }

                    //Delete not selected user role
                    var deletedUserRoleRecord = retrieveRoleResponse.Records.Where(x => objectRoles.Any(y => y.RoleIdentifier == x.RoleIdentifier && y.ObjectIdentifier == x.ObjectIdentifier)
                                                                                      && groupRoles.Any(z => z.Active != false && z.GroupIdentifier == selectedGroupIdentifier && z.ObjectIdentifier == x.ObjectIdentifier && z.RoleIdentifier == x.RoleIdentifier)).ToList();
                    if (deletedUserRoleRecord != null && deletedUserRoleRecord.Count > 0)
                    {
                        var deletedUserRoleRequest = new DeleteUserRolesRequest { Record = deletedUserRoleRecord, Header = header };
                        var deletedUserRoleResponse = serviceClient.Proxy.DeleteUserRoles(deletedUserRoleRequest);
                        if (!deletedUserRoleResponse.IsSuccess)
                        {
                            UpdateUserRoleViewModel(serviceClient, header, vm, dictUsers);
                            vm.Message = deletedUserRoleResponse.ErrorMessage;
                            vm.MessageType = MessageType.Error;
                            vm.Message = vm.Message;
                            return View(vm);
                        }
                    }

                    //Add selected user role
                    var savedUserRoleRecords = objectRoles.Where(x => !groupRoles.Any(z => z.Active != false && z.ObjectIdentifier == x.ObjectIdentifier && z.RoleIdentifier == x.RoleIdentifier && z.GroupIdentifier == selectedGroupIdentifier))
                        .Select(item => new UserRoleRecord
                    {
                        ApplicationKey = SystemConfiguration.ApplicationKey,
                        UserName = vm.UserName,
                        ObjectIdentifier = item.ObjectIdentifier,
                        RoleIdentifier = item.RoleIdentifier,
                        Active = true
                    }).ToList();
                    if (savedUserRoleRecords != null && savedUserRoleRecords.Count > 0)
                    {
                        var savedUserRoleRequest = new SaveUserRolesRequest { Record = savedUserRoleRecords, Header = header };
                        var savedUserRoleResponse = serviceClient.Proxy.SaveUserRoles(savedUserRoleRequest);
                        if (!savedUserRoleResponse.IsSuccess)
                        {
                            UpdateUserRoleViewModel(serviceClient, header, vm, dictUsers);
                            vm.Message = savedUserRoleResponse.ErrorMessage;
                            vm.MessageType = MessageType.Error;
                            vm.Message = vm.Message;
                            return View(vm);
                        }
                    }
                }
                return Redirect("/account/assign-user-objects");
            }
        }

        [Authorize]
        [HttpPost]
        public ActionResult Objects_In_User(string username, string otp, ulong counter)
        {
            OTP.Instant.Counter = counter;
            DateTime timeGet; bool validateOtp = false;
            if (DateTime.TryParseExact(counter.ToString(), SystemConfiguration.CounterDateTimeFormat, null, DateTimeStyles.None, out timeGet))
            {
                TimeSpan timeCheck = DateTime.UtcNow - timeGet;
                if (timeCheck.TotalSeconds <= SystemConfiguration.OTPLiveTime) validateOtp = true;
            }

            if (!validateOtp || OTP.Instant.GetCurrentOTP() != otp)
            {
                ResponseRecord res = new ResponseRecord
                {
                    IsSuccess = false,
                    ErrorMessage = "Invalidate OTP check request"
                };
                return Json(res);
            }

            if (username.IsNullOrWhiteSpace())
            {
                ResponseRecord res2 = new ResponseRecord
                {
                    IsSuccess = false,
                    ErrorMessage = "Invalidate username request - request null"
                };
                return Json(res2);
            }

            var header = new RequestHeaderRecord
            {
                ApplicationKey = SystemConfiguration.ApplicationKey,
                CallerName = "Authentication.Web.Controller.AccountController.Objects_In_User"
            };

            using (ServiceClient<IAuthentication> serviceClient = new ServiceClient<IAuthentication>())
            {

                RetrieveUsersRequest retrieveRequest = new RetrieveUsersRequest { Header = header, GroupIdentifier = username };
                var response = serviceClient.Proxy.RetrieveUsers(retrieveRequest);
                if (response.IsSuccess)
                {
                    var records = response.Records;
                }
                else
                {
                    response.ErrorMessage = string.Format("Can not found any user with username='{0}'", username);
                }
                return Json(response);
            }
        }
        #endregion

        #region Helper funcions
        private ActionResult AssignAnUserToGroup(ServiceClient<IAuthentication> serviceClient, RequestHeaderRecord header, string groupidentifier, string username, bool ischecked)
        {
            RetrieveUserByUserNameRequest retrieveRequest = new RetrieveUserByUserNameRequest { Header = header, UserName = username };
            var retrieveResponse = serviceClient.Proxy.RetrieveUserByUserName(retrieveRequest);
            if (retrieveResponse.IsSuccess)
            {
                UserRecord userRecord = retrieveResponse.Record;
                userRecord.GroupIdentifier = groupidentifier;
                if (ischecked) userRecord.GroupIdentifier = groupidentifier;
                else userRecord.GroupIdentifier = string.Empty;
                UpdateUserRequest request = new UpdateUserRequest { Header = header, Record = userRecord };
                var response = serviceClient.Proxy.UpdateUser(request);
                if (response.IsSuccess)
                {
                    return Json(response);
                }
                else
                {
                    response.ErrorMessage = string.Format("Can not update user with Username='{0}', GroupIdentifier='{1}'", username, groupidentifier);
                    return Json(response);
                }
            }
            else
            {
                retrieveResponse.ErrorMessage = string.Format("Can not found user with Username='{0}'", username);
                return Json(retrieveResponse);
            }
        }

        private ActionResult AssignUsersToGroup(ServiceClient<IAuthentication> serviceClient, RequestHeaderRecord header, string groupidentifier, List<string> usersname)
        {
            if (groupidentifier.IsNullOrWhiteSpace())
            {
                return Json(new ResponseRecord { ErrorMessage = "The groupidentifier must be set" });
            }

            RetrieveUsersRequest retrieveRequest = new RetrieveUsersRequest { Header = header, GroupIdentifier = groupidentifier };
            var retrieveResponse = serviceClient.Proxy.RetrieveUsers(retrieveRequest);
            if (retrieveResponse.IsSuccess)
            {
                var userRecords = retrieveResponse.Records;
                var removeRecord = userRecords.Where(x => !usersname.Any(y => (x.UserName == y)));
                foreach (var item in removeRecord)
                {
                    item.GroupIdentifier = string.Empty;
                    UpdateUserRequest request = new UpdateUserRequest { Header = header, Record = item };
                    var response = serviceClient.Proxy.UpdateUser(request);
                    if (response.IsSuccess)
                    {
                        return Json(response);
                    }
                    else
                    {
                        response.ErrorMessage = string.Format("Can not update user with Username='{0}', GroupIdentifier='{1}'", item.UserName, groupidentifier);
                        return Json(response);
                    }
                }

                var oldRecords = userRecords.Where(x => usersname.Any(y => (x.UserName == y)));
                var addedRecords = usersname.Where(x => (!oldRecords.Any(y => y.UserName == x) && (!removeRecord.Any(z => z.UserName == x))));

                bool isSuccess = true;
                string errorMsg = string.Empty;
                foreach (var item in addedRecords)
                {
                    RetrieveUserByUserNameRequest retrieveUserRequest = new RetrieveUserByUserNameRequest { Header = header, UserName = item };
                    var retrieveUserResponse = serviceClient.Proxy.RetrieveUserByUserName(retrieveUserRequest);
                    if (retrieveResponse.IsSuccess)
                    {
                        UserRecord userRecord = retrieveUserResponse.Record;
                        userRecord.GroupIdentifier = groupidentifier;

                        UpdateUserRequest request = new UpdateUserRequest { Header = header, Record = userRecord };
                        var response = serviceClient.Proxy.UpdateUser(request);
                        if (response.IsSuccess)
                        {
                            errorMsg = response.ErrorMessage;
                            isSuccess = response.IsSuccess;
                        }
                        else
                        {
                            errorMsg = string.Format("Can not update user with Username='{0}', GroupIdentifier='{1}'", item, groupidentifier);
                            isSuccess = false;
                        }
                    }
                    else
                    {
                        errorMsg = string.Format("Can not found user with Username='{0}'", item);
                        isSuccess = false;
                    }
                }
                return Json(new ResponseRecord { ErrorMessage = errorMsg, IsSuccess = isSuccess });
            }
            else
            {
                retrieveResponse.ErrorMessage = string.Format("Can not found any users with GroupIdentifier='{0}'", groupidentifier);
                return Json(retrieveResponse);
            }
        }

        private void UpdateGroupRoleViewModel(ServiceClient<IAuthentication> serviceClient, RequestHeaderRecord header, AssignGroupObjectViewModel vm)
        {
            RetrieveGroupRolesRequest requestGroupRoles = new RetrieveGroupRolesRequest { Header = header };
            var retrieveGroupRolesResponse = serviceClient.Proxy.RetrieveGroupRoles(requestGroupRoles);
            if (retrieveGroupRolesResponse.IsSuccess)
            {
                vm.ObjectRoleIdentifiers = new List<string>();
                vm.ObjectRole_GroupIdentifier = new Dictionary<string, string>();
                for (int i = 0; i < retrieveGroupRolesResponse.Records.Count; i++)
                {
                    var x = retrieveGroupRolesResponse.Records[i];
                    var key = string.Format("ObjectIdentifier:\"{0}\",RoleIdentifier:\"{1}\"", x.ObjectIdentifier, x.RoleIdentifier);
                    var value = x.GroupIdentifier;
                    vm.ObjectRoleIdentifiers.Add(key);

                    if (!vm.ObjectRole_GroupIdentifier.ContainsKey(key))
                        vm.ObjectRole_GroupIdentifier.Add(key, value);
                    else
                        vm.ObjectRole_GroupIdentifier[key] += string.Format(";{0}", value);
                }

            }
        }

        private void UpdateUserRoleViewModel(ServiceClient<IAuthentication> serviceClient, RequestHeaderRecord header, AssignUserObjectViewModel vm, Dictionary<string, UserRecord> dictUsers)
        {
            RetrieveGroupRolesRequest requestGroupRoles = new RetrieveGroupRolesRequest { Header = header };
            var retrieveGroupRolesResponse = serviceClient.Proxy.RetrieveGroupRoles(requestGroupRoles);

            //Check user roles
            var ObjectRole_UserName = new Dictionary<string, Dictionary<string, ActiveItem>>();
            RetrieveUserRolesRequest requestUserRoles = new RetrieveUserRolesRequest { Header = header };
            var retrieveUserRolesResponse = serviceClient.Proxy.RetrieveUserRoles(requestUserRoles);
            if (retrieveUserRolesResponse.IsSuccess)
            {
                for (int i = 0; i < retrieveUserRolesResponse.Records.Count; i++)
                {
                    var userRole = retrieveUserRolesResponse.Records[i];
                    var key = string.Format("ObjectIdentifier:\"{0}\",RoleIdentifier:\"{1}\"", userRole.ObjectIdentifier, userRole.RoleIdentifier);
                    var valueAct = new ActiveItem(userRole.UserName, userRole.Active);
                    if (!dictUsers[userRole.UserName].Active) valueAct.Active = false;
                    var value = userRole.UserName;
                    if (!ObjectRole_UserName.ContainsKey(key))
                    {
                        Dictionary<string, ActiveItem> valueDct = new Dictionary<string, ActiveItem>();
                        valueDct.Add(userRole.UserName, valueAct);
                        ObjectRole_UserName.Add(key, valueDct);
                    }
                    else if (!ObjectRole_UserName[key].ContainsKey(value))
                    {
                        ObjectRole_UserName[key].Add(value, valueAct);
                    }
                }
            }

            //Check group roles
            var ObjectRole_GroupIdentifier = new Dictionary<string, Dictionary<string, ActiveItem>>();
            if (retrieveGroupRolesResponse.IsSuccess)
            {
                for (int i = 0; i < retrieveGroupRolesResponse.Records.Count; i++)
                {
                    var groupRole = retrieveGroupRolesResponse.Records[i];
                    var key = string.Format("ObjectIdentifier:\"{0}\",RoleIdentifier:\"{1}\"", groupRole.ObjectIdentifier, groupRole.RoleIdentifier);
                    var values = vm.Users.Where(x => x.GroupIdentifier == groupRole.GroupIdentifier).ToDictionary(x => x.UserName, y => new ActiveItem(y.UserName, y.Active));

                    if (!ObjectRole_GroupIdentifier.ContainsKey(key))
                    {
                        ObjectRole_GroupIdentifier.Add(key, values);
                    }

                    //-Add to existing user
                    if (ObjectRole_UserName.ContainsKey(key))
                    {
                        foreach (var value in values.Values)
                        {
                            if (!ObjectRole_UserName[key].ContainsKey(value.Value))
                            {
                                ObjectRole_UserName[key].Add(value.Value, value);
                            }
                            else if (!(ObjectRole_UserName[key])[value.Value].Active)
                            {
                                (ObjectRole_UserName[key])[value.Value].Active = false;
                            }
                        }
                    }
                    else
                    {
                        ObjectRole_UserName.Add(key, values);
                    }
                }
            }

            //summary
            vm.ObjectRole_UserName = ObjectRole_UserName.ToDictionary(x => x.Key, y => y.Value.Values.Where(z => z.Active != false).ToDictionary(m => m.Value, n => n.Value));
        }
        #endregion
    }
}
